package com.sa.commons.dao.hiber;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;

import com.sa.commons.dao.hiber.basic.HibernateSessionFactory;
import com.sa.commons.dao.hiber.inter.GenericDao;

import com.sa.commons.exception.DBDataErrorException;
import com.sa.commons.exception.DBErrorException;

public class GenericDaoImpl<PK,E> implements GenericDao<PK, E> {
	
	private static Log log=LogFactory.getLog(GenericDaoImpl.class);
	
	protected Class<? extends E> entityClass;
	
	
	/**
	 * 根据实体类对象构造DAO
	 * 
	 * @param entityClass
	 *            实体类对象
	 */
	public GenericDaoImpl(Class<? extends E> entityClass) {
		this.entityClass = entityClass;
	}

	/**
	 * 根据实体类的类名构造DAO
	 * 
	 * @param entityClassName
	 *            实体类的类名
	 */
	@SuppressWarnings("unchecked")
	public GenericDaoImpl(String entityClassName) {
		try {
			this.entityClass = (Class<? extends E>) Class
					.forName(entityClassName);
		} catch (ClassNotFoundException e) {
			log.error("class for name " + entityClassName + "not found!", e);
		}
	}
	
	public void delete(PK id)throws DBErrorException,DBDataErrorException{
		log.debug("delete for class=" + entityClass.getName());
		try {
			getSession().createQuery(
					"delete from " + entityClass.getName() + " as clazz where "
							+ "id" + " = '" + id + "'").executeUpdate();
		} catch (RuntimeException re) {
			log.error("delete for class=" + entityClass.getName() + " failed!",
					re);
			throw new DBDataErrorException("删除" + id + " 对应的记录失败");
		}
	}

	@SuppressWarnings("unchecked")
	public E get(PK id) throws DBErrorException,DBDataErrorException {
		log.debug("get for class=" + entityClass.getName());

		try {
			return (E) getSession().createQuery(
					"from " + entityClass.getName() + " as clazz where "
					    +"id" + " = '" + id + "'").uniqueResult();
		} catch (RuntimeException re) {
			log.error("get for class=" + entityClass.getName()
							+ " failed!", re);
			throw new DBDataErrorException("查找" + id + " 对应的记录失败");
		}
	}

	public E getForUpdate(PK id) throws DBErrorException,DBDataErrorException {
		log.debug("getForUpdate for class=" + entityClass.getName()
				+ "for update");
		try {
			E entity=get(id);
			update(entity);
			return entity;
		} catch (RuntimeException re) {
			log.error("getForUpdate for class=" + entityClass.getName()
					+ " for getForUpdate failed!", re);
			throw new DBDataErrorException("查找" + id + " 对应的记录失败");
		}
	}

	public Session getSession() {
		return HibernateSessionFactory.getSession();
	}

	public E save(E entity) throws DBErrorException,DBDataErrorException {
		log.debug("save for class=" + entityClass.getName());
		try {
			getSession().save(entity);
			return entity;
		} catch (RuntimeException re) {
			log.error("save for class=" + entityClass.getName() + " failed!",
					re);
			re.printStackTrace();
			throw new DBDataErrorException("保存" + entityClass.getName() + " 类的记录失败");
		}
	}

	public E update(E entity) throws DBErrorException,DBDataErrorException {
		log.debug("update for class=" + entityClass.getName());
		try {
			getSession().update(entity);
			return entity;
		} catch (RuntimeException re) {
			log.error("update for class=" + entityClass.getName() + " failed!",
					re);
			re.printStackTrace();
			throw new DBDataErrorException("修改" + entityClass.getName() + " 类的记录失败");
		}
	}

	public E saveOrUpdate(E entity) throws DBErrorException,DBDataErrorException{
		log.debug("update for class=" + entityClass.getName());
		try {
			getSession().saveOrUpdate(entity);
			return entity;
		} catch (RuntimeException re) {
			log.error("update for class=" + entityClass.getName() + " failed!",
					re);
			re.printStackTrace();
			throw new DBDataErrorException("修改或保存" + entityClass.getName() + " 类的记录失败");
		}
	}

}
